#include "arch_linux.h"
#include <ctime>
#include <iostream>
#include <fstream>

// ? Functions
void Arch_linux::clear_display()
{
    system("clear");
}
void Arch_linux::enableInternet()
{
    system("echo \"\n[SET UP INTERNET]\" && sleep 1");
    system("dhclient -4");
}
void Arch_linux::Update()
{
    system("echo \"\n[UPDATE]\" && sleep 1");
    system("pacman -Syu --noconfirm");
}
void Arch_linux::loadkeys_us() 
{
    system("echo \"\n[SET LOADKEYS TO US]\" && sleep 1");
    system("loadkeys us");
}
void Arch_linux::install_cryptsetup_and_lvm()
{
    system("echo \"\n[INSTALL CRYPTSETUP, LVM]\" && sleep 1");
    system("pacman -Syy cryptsetup lvm2 --noconfirm");
}
void Arch_linux::addService(std::string deamon, std::string level) {
    system("echo \"\n[ENABLE SEVICE]\" && sleep 1");
    system(("rc-update add " + deamon + " " + level).data());
}
void Arch_linux::modprobe(std::string module)
{
    system("echo \"\n[ENABLE MODULE]\" && sleep 2");
    system(("modprobe " + module).data());
}
void Arch_linux::configurate_disk_for_grub()
{
    system("echo \"\n[PARTION GRUB CONFIGURATION]\" && sleep 2");
    system(("sfdisk --delete " + this->disk_grub).data()); 
    system(("parted " + this->disk_grub + " mkpart primary 0% 600MB").data());   
    system(("mkfs.ext2 " + this->partion_grub).data());
}
void Arch_linux::format_partion(std::string partion, std::string file_system)
{
    system(("mkfs." + file_system + " " + partion).data());
}
void Arch_linux::encrypt_luks_partion()
{
    system("echo \"\n[LUKS Encryption]\" && sleep 2");
    this->format_partion(this->partion_luks, "ext4");
    system(("cryptsetup -v --cipher serpent-xts-plain64 --key-size 512 --hash whirlpool --iter-time 500 --use-random --verify-passphrase luksFormat " + this->partion_luks).data());
}
void Arch_linux::create_lvm()
{
    system("echo \"[CREATE LVM]\" && sleep 2");
    system("pvcreate /dev/mapper/lvm");
}
void Arch_linux::create_lvm_group()
{
    system("vgcreate glvm /dev/mapper/lvm");
}
void Arch_linux::create_lvm_volume_swap()
{
    system(("lvcreate -L " + this->size_lvm_volume_swap + " " + this->lvm_group + " -n swapvol").data());
}
void Arch_linux::create_lvm_volume_root()
{
    system(("lvcreate -L " + this->size_lvm_volume_root + " " + this->lvm_group + " -n rootvol").data());
}
void Arch_linux::create_lvm_volume_home()
{
    system(("lvcreate -L +100%FREE " + this->lvm_group + " -n homevol").data());
}
void Arch_linux::create_swap_lvm_partion()
{
    system("echo \"[CREATE SWAP partion]\" && sleep 2");
    system(("mkswap /dev/mapper/"+this->lvm_group+"-swapvol").data());
}
void Arch_linux::enable_swap_lvm_partion()
{
    system(("swapon /dev/"+this->lvm_group+"/swapvol").data());
}
void Arch_linux::format_lvm_and_grub_partions()
{
    this->format_partion(("/dev/mapper/"+this->lvm_group+"-rootvol").data(),"ext4");
    this->format_partion(("/dev/mapper/"+this->lvm_group+"-homevol").data(),"ext4");
    this->format_partion(this->partion_grub, "ext2");
}
void Arch_linux::mount_lvm_root()
{
    system("echo \">>> [MOUNT PARTIONS]\" && sleep 2");
    system(("mount /dev/"+this->lvm_group+"/rootvol /mnt").data());
}
void Arch_linux::mount_lvm_home()
{
    system("mkdir -p /mnt/home");
    system(("mount /dev/"+this->lvm_group+"/homevol /mnt/home").data());
}
void Arch_linux::mount_lvm_boot()
{
    system("mkdir -p /mnt/boot");
    system(("mount " + this->partion_grub + " /mnt/boot").data());
}
void Arch_linux::install()
{
    system("clear");
    system("echo \"\n[INSTALL SYSTEM]\" && sleep 2");
    system(("pacstrap /mnt base " + this->packages).data());
}

void Arch_linux::generate_fstab()
{
    system("echo \"\n[GENERATE FSTAB]\" && sleep 2");
    system("genfstab -U -p /mnt >> /mnt/etc/fstab");
}

void Arch_linux::copy_second_script()
{
    system("cp -fv install_chroot /mnt/");
    system("chmod +x /mnt/install_chroot");
}
void Arch_linux::write_variables_to_file()
{
    system("rm -f /mnt/variables.txt"); // if file is created after  
    system(("echo \"" + this->timezone + "\" >> /mnt/variables.txt").data());
    system(("echo \"" + this->hostname + "\" >> /mnt/variables.txt").data());
    system(("echo \"" + this->user_name + "\" >> /mnt/variables.txt").data());
    system(("echo \"" + this->disk_grub + "\" >> /mnt/variables.txt").data());
    system(("blkid -o value -s UUID " + this->partion_luks + ">> /mnt/variables.txt").data());
    system(("blkid -o value -s UUID /dev/"+this->lvm_group+"/rootvol >> /mnt/variables.txt").data());
    system(("echo \"" + this->kernel + "\" >> /mnt/variables.txt").data());

}
void Arch_linux::chroot_and_start_second_script()
{
    system("echo \"\n[Chroot]\" && sleep 2");
    system("arch-chroot /mnt ./install_chroot");
}

void Arch_linux::read_variables_from_file()
{
    std::ifstream file( "variables.txt" );
    file >> this->timezone;
    file >> this->hostname;
    file >> this->user_name;
    file >> this->disk_grub;
    file >> this->partion_luks_uuid;
    file >> this->lvm_volume_root_uuid;
    file >> this->kernel;
    file.close();
}
void Arch_linux::install_packages(std::string packages)
{
    system(("pacman -S " + packages + " --noconfirm").data());
}
void Arch_linux::generate_locale_us_ru()
{
    system("echo \"en_US.UTF-8 UTF-8\" >> /etc/locale.gen");
    system("echo \"ru_RU.UTF-8 UTF-8\" >> /etc/locale.gen");
    system("locale-gen");
}
void Arch_linux::link_timezone()
{
    system(("ln -s " + this->timezone + " /etc/localtime").data());
}

void Arch_linux::create_files_hostname_and_hosts()
{
    system(("echo " + this->hostname + " > /etc/hostname").data());
    system(("echo \"127.0.0.1               localhost.localdomain       localhost  " + this->hostname + " \" >> /etc/hosts").data());
    system(("echo \"::1                     localhost.localdomain       localhost  " + this->hostname + " \" >> /etc/hosts").data());
}
void Arch_linux::configurate_mkinitcpio()
{
    system("sed -i \"s/HOOKS=\\\"base udev autodetect modconf block filesystems keyboard fsck\\\"/HOOKS=\\\"base udev autodetect modconf block keyboard encrypt lvm2 filesystems fsck shutdown\\\"/g\" /etc/mkinitcpio.conf");
    system(("mkinitcpio -p " + this->kernel).data());
}
void Arch_linux::add_user(std::string user_name)
{
    system(("useradd -m -G audio,disk,games,http,input,lp,network,optical,power,scanner,storage,sys,video,wheel -g users -s /bin/bash " + user_name).data());
}
void Arch_linux::set_user_password(std::string user_name)
{
    system(("passwd " + user_name).data());
}
void Arch_linux::add_user_in_group(std::string user_name, std::string group_name)
{
    system(("gpasswd -a " + user_name + " " + group_name).data());
}
void Arch_linux::chmod_nftables()
{
    system("chmod 700 /boot /etc/nftables.rules");  
}
void Arch_linux::configurate_grub()
{
    system(("sed -i \"s/GRUB_CMDLINE_LINUX_DEFAULT=\\\"quiet\\\"/GRUB_CMDLINE_LINUX_DEFAULT=\\\"loglevel=3 quiet cryptdevice=UUID=" + this->partion_luks_uuid + ":glvm root=UUID=" + this->lvm_volume_root_uuid + " video=\\\"1920x1080\\\"" + "\\\"/g\" /etc/default/grub").data());
    system("sed -i \"s/#GRUB_ENABLE_CRYPTODISK=y/GRUB_ENABLE_CRYPTODISK=y/\" /etc/default/grub");
    system("sed -i \"s/GRUB_TIMEOUT=5/GRUB_TIMEOUT=1/\" /etc/default/grub");
}
void Arch_linux::install_grub_to_disk()
{
    system(("grub-install --target=i386-pc --recheck " + this->disk_grub).data());
    system("grub-mkconfig -o /boot/grub/grub.cfg");
}

void Arch_linux::link_boot_partion()
{
    system("cd /boot && ln -s . boot");
}

// ? Setters
void Arch_linux::set_partion_luks(std::string partion)
{
    this->partion_luks = partion;
}

void Arch_linux::set_size_lvm_volume_root(std::string size)
{
    this->size_lvm_volume_root = size;
}
void Arch_linux::set_size_lvm_volume_swap(std::string size)
{
    this->size_lvm_volume_swap = size;
}
void Arch_linux::set_grub_disk(std::string disk)
{
    this->disk_grub = disk;
}

void Arch_linux::set_packages(std::string packages)
{
    this->packages = packages;
}

void Arch_linux::set_timezone(std::string timezone)
{
    this->timezone = "/usr/share/zoneinfo/" + timezone;
}

void Arch_linux::set_hostname(std::string name)
{
    this->hostname = name;
}

void Arch_linux::set_user_name(std::string name)
{
    this->user_name = name;
}
void Arch_linux::set_lvm_group(std::string name)
{
    this->lvm_group = name;
}
void Arch_linux::set_kernel(std::string name)
{
    this->kernel = name;
}
// ? getters
std::string Arch_linux::get_partion_luks()  { return this->partion_luks; }
std::string Arch_linux::get_grub_disk() { return this->disk_grub; }
std::string Arch_linux::get_packages()  { return this->packages; }
std::string Arch_linux::get_timezone()  { return this->timezone; }
std::string Arch_linux::get_hostname()  { return this->hostname; }
std::string Arch_linux::get_user_name() { return this->user_name; }
std::string Arch_linux::get_lvm_group() { return this->lvm_group; }
std::string Arch_linux::get_kernel()    { return this->kernel; }
